<?php
namespace App\Logics\Common;
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
 * Http 工具类
 * 提供一系列的Http方法
 *
 * @author liu21st <liu21st@gmail.com>
 */
class Http {

    /**
     * 模拟登陆
     */
    function vpost($url, $data, $cookie, $referer, $path = 'cookie.txt', $read_cookie = '', $ips = array()) {
        // 模拟提交数据函数
        $curl = curl_init ();
        // 启动一个CURL会话
        curl_setopt ( $curl, CURLOPT_URL, $url );
        // 读取cookie
        if ($read_cookie != '') {
            curl_setopt ( $curl, CURLOPT_COOKIEFILE, $read_cookie );
        }
        if (empty ( $ips )) {
            $ips = array (
                'CLIENT-IP:116.226.153.11',
                'X-FORWARDED-FOR:116.226.153.11'
            );
        }
        // 要访问的地址
        curl_setopt ( $curl, CURLOPT_SSL_VERIFYPEER, 0 );
        // 对认证证书来源的检查
        // curl_setopt ( $curl, CURLOPT_SSL_VERIFYHOST, 1 );
        curl_setopt ( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
        // 从证书中检查SSL加密算法是否存在
        curl_setopt ( $curl, CURLOPT_USERAGENT, $_SERVER ['HTTP_USER_AGENT'] );
        curl_setopt ( $curl, CURLOPT_HTTPHEADER, $ips ); // 伪造iP
        // 模拟用户使用的浏览器
        curl_setopt ( $curl, CURLOPT_COOKIE, $cookie );
        curl_setopt ( $curl, CURLOPT_REFERER, $referer );
        // 设置Referer
        curl_setopt ( $curl, CURLOPT_POST, 1 );
        // 发送一个常规的Post请求
        curl_setopt ( $curl, CURLOPT_POSTFIELDS, $data );
        // Post提交的数据包
        curl_setopt ( $curl, CURLOPT_TIMEOUT, 30 );
        // 设置超时限制防止死循环
        curl_setopt ( $curl, CURLOPT_HEADER, 0 );
        // 显示返回的Header区域内容
        curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, 1 );
        // 获取的信息以文件流的形式返回
        curl_setopt ( $curl, CURLOPT_FOLLOWLOCATION, true );
        // 设置文件读取并提交的cookie路径
        curl_setopt ( $curl, CURLOPT_COOKIEJAR, $path );
        // 保存
        $tmpInfo = curl_exec ( $curl );
        // 执行操作
        if (curl_errno ( $curl )) {
            echo 'Errno' . curl_error ( $curl );
            // 捕抓异常
        }
        curl_close ( $curl );
        // 关闭CURL会话
        return $tmpInfo;
        // 返回数据
    }

    /**
     * 请求文件
     */
    function request_url_data($url, $path = 'cookie.txt') {
        // 初始化，创建一个新cURL资源
        $ch = curl_init ();
        // 读取cookie
        curl_setopt ( $ch, CURLOPT_COOKIEFILE, $path );
        // 设置URL和相应的选项
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        // 抓取URL并把它传递给浏览器
        $data = curl_exec ( $ch );
        // 关闭cURL资源，并且释放系统资源
        curl_close ( $ch );
        return $data;
    }

    /**
     * 发起HTTPS请求
     */
    public  static function curl_post($url, $data, $path = 'cookie.txt', $referer = '', $httpHeader = '') {
        $post_data = $data; // array($key=>$value)
        $ch = curl_init (); // 初始化curl

        //将https 变为http方式post
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

        // 读取cookie
        curl_setopt ( $ch, CURLOPT_COOKIEFILE, $path );
        // 参数设置
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        // post数据
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        // refere
        if ($referer != '') {
            curl_setopt ( $ch, CURLOPT_REFERER, $referer );
        }
        // post的变量
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );
        if (! empty ( $httpHeader ) && is_array ( $httpHeader )) {
            curl_setopt ( $ch, CURLOPT_HTTPHEADER, $httpHeader );
        }
        $result = curl_exec ( $ch );
        if ($result === FALSE)         // 连接失败
        {
            print curl_error ( $ch );
        }
        curl_close ( $ch );
        return $result;
    }

    // Add by jungil
    public static function curl_post2($url, $data, $httpHeader = []) {
        $ch = curl_init (); // 初始化curl
        // 参数设置
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
        // post数据
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        // post的变量
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        if (! empty ( $httpHeader ) && is_array ( $httpHeader )) {
            curl_setopt ( $ch, CURLOPT_HTTPHEADER, $httpHeader );
        }
        $result = curl_exec ( $ch );
        curl_close ( $ch );

        return $result;
    }

    public static function curl_post3($url, $data, $cainfo_url,$key_url,$rootca_url, $httpHeader = []) {
        $ch = curl_init (); // 初始化curl
        // 参数设置
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

        curl_setopt($ch, CURLOPT_SSLCERT,$cainfo_url);
        curl_setopt($ch, CURLOPT_SSLKEY,$key_url);
        curl_setopt($ch, CURLOPT_CAINFO,$rootca_url);

//        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
//        curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
//echo $cainfo_url;exit;
//        curl_setopt($ch, CURLOPT_SSLCERT, $cainfo_url);

        // post数据
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        // post的变量
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        if (! empty ( $httpHeader ) && is_array ( $httpHeader )) {
            curl_setopt ( $ch, CURLOPT_HTTPHEADER, $httpHeader );
        }
        $result = curl_exec ( $ch );
        curl_close ( $ch );

        return $result;
    }

    /**
     * application/json 方式
     * @param $url
     * @param $jsonStr
     * @return array
     *
     * @author Win
     */
    public static function curl_post_json($url, $jsonStr){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length: ' . strlen($jsonStr),
            )
        );
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        return array( $httpCode, $response );
    }

    public static function curl_get($url, $path = 'cookie.txt', $cookie = '', $httpHeader = []) {
        // 初始化
        $ch = curl_init ();
        if ($path) {
            // 读取cookie
            curl_setopt ( $ch, CURLOPT_COOKIEFILE, $path );
        }
        $ssl = strpos ( $url, "https" ) === false ? false : true;
        // 设置选项，包括URL
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        // 从证书中检查SSL加密算法是否存在
        curl_setopt ( $ch, CURLOPT_USERAGENT, $_SERVER ['HTTP_USER_AGENT'] );
        if ($ssl) {
            curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, 2 );
            curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
        }
        if (! empty ( $httpHeader ) && is_array ( $httpHeader )) {
            curl_setopt ( $ch, CURLOPT_HTTPHEADER, $httpHeader );
        }
        /*
         * $ips = array( 'CLIENT-IP:1.1.1.1', 'X-FORWARDED-FOR:1.1.1.1', ); curl_setopt($ch, CURLOPT_HTTPHEADER, $ips);//伪造iP
         */
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        if ($cookie) {
            // 写入验证码
            curl_setopt ( $ch, CURLOPT_COOKIEJAR, $cookie );
        }
        curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, true );
        // 执行并获取HTML文档内容
        $output = curl_exec ( $ch );
        // 释放curl句柄
        curl_close ( $ch );
        // 打印获得的数据
        return $output;
    }

    public static function curl_get2($url)
    {
        //初始化
        $ch = curl_init();
        //设置选项，包括URL
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        //执行并获取HTML文档内容
        $output = curl_exec($ch);
        //释放curl句柄
        curl_close($ch);
        //打印获得的数据
        return $output;
    }

    public static function curl_get3($url, $cookie) {
        // 初始化
        $ch = curl_init ();
        // 设置选项，包括URL
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        curl_setopt ( $ch, CURLOPT_COOKIE, $cookie );
//        curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, true );
        // 执行并获取HTML文档内容
        $output = curl_exec ( $ch );
        // 释放curl句柄
        curl_close ( $ch );
        // 打印获得的数据
        return $output;
    }


    public static function curl_delete($url,$header=[]) {
        // 初始化
        $ch = curl_init ();
        // 设置选项，包括URL
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
        if($header){
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //模拟的header头
        }
//        curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, true );
        // 执行并获取HTML文档内容
        $output = curl_exec ( $ch );
        // 释放curl句柄
        curl_close ( $ch );
        // 打印获得的数据
        return $output;
    }


    function getCode($url, $cookieFile, $read = '') {
        $ch = curl_init ( $url );
        if ($read) {
            // 读取cookie
            curl_setopt ( $ch, CURLOPT_COOKIEFILE, $read );
        }
        $ssl = strpos ( $url, "https" ) === false ? false : true;
        if ($ssl) {
            curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, 2 );
            curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
        }
        if (! empty ( $cookieFile )) {
            // 把返回来的cookie信息保存在文件中
            curl_setopt ( $ch, CURLOPT_COOKIEJAR, $cookieFile );
        }
        curl_exec ( $ch );
        curl_close ( $ch );
    }
    /**
     * 采集远程文件
     *
     * @access public
     * @param string $remote
     *            远程文件名
     * @param string $local
     *            本地保存文件名
     * @return mixed
     */
    static public function curlDownload($remote, $local) {
        $cp = curl_init ( $remote );
        $fp = fopen ( $local, "w" );
        curl_setopt ( $cp, CURLOPT_FILE, $fp );
        curl_setopt ( $cp, CURLOPT_HEADER, 0 );
        curl_exec ( $cp );
        curl_close ( $cp );
        fclose ( $fp );
    }

    /**
     * 使用 fsockopen 通过 HTTP 协议直接访问(采集)远程文件
     * 如果主机或服务器没有开启 CURL 扩展可考虑使用
     * fsockopen 比 CURL 稍慢,但性能稳定
     *
     * @static
     *
     * @access public
     * @param string $url
     *            远程URL
     * @param array $conf
     *            其他配置信息
     *            int limit 分段读取字符个数
     *            string post post的内容,字符串或数组,key=value&形式
     *            string cookie 携带cookie访问,该参数是cookie内容
     *            string ip 如果该参数传入,$url将不被使用,ip访问优先
     *            int timeout 采集超时时间
     *            bool block 是否阻塞访问,默认为true
     * @return mixed
     */
    static public function fsockopenDownload($url, $conf = array()) {
        $return = '';
        if (! is_array ( $conf ))
            return $return;

        $matches = parse_url ( $url );
        ! isset ( $matches ['host'] ) && $matches ['host'] = '';
        ! isset ( $matches ['path'] ) && $matches ['path'] = '';
        ! isset ( $matches ['query'] ) && $matches ['query'] = '';
        ! isset ( $matches ['port'] ) && $matches ['port'] = '';
        $host = $matches ['host'];
        $path = $matches ['path'] ? $matches ['path'] . ($matches ['query'] ? '?' . $matches ['query'] : '') : '/';
        $port = ! empty ( $matches ['port'] ) ? $matches ['port'] : 80;

        $conf_arr = array (
            'limit' => 0,
            'post' => '',
            'cookie' => '',
            'ip' => '',
            'timeout' => 15,
            'block' => TRUE
        );

        foreach ( array_merge ( $conf_arr, $conf ) as $k => $v )
            ${$k} = $v;

        if ($post) {
            if (is_array ( $post )) {
                $post = http_build_query ( $post );
            }
            $out = "POST $path HTTP/1.0\r\n";
            $out .= "Accept: */*\r\n";
            // $out .= "Referer: $boardurl\r\n";
            $out .= "Accept-Language: zh-cn\r\n";
            $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
            $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
            $out .= "Host: $host\r\n";
            $out .= 'Content-Length: ' . strlen ( $post ) . "\r\n";
            $out .= "Connection: Close\r\n";
            $out .= "Cache-Control: no-cache\r\n";
            $out .= "Cookie: $cookie\r\n\r\n";
            $out .= $post;
        } else {
            $out = "GET $path HTTP/1.0\r\n";
            $out .= "Accept: */*\r\n";
            // $out .= "Referer: $boardurl\r\n";
            $out .= "Accept-Language: zh-cn\r\n";
            $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
            $out .= "Host: $host\r\n";
            $out .= "Connection: Close\r\n";
            $out .= "Cookie: $cookie\r\n\r\n";
        }
        $fp = @fsockopen ( ($ip ? $ip : $host), $port, $errno, $errstr, $timeout );
        if (! $fp) {
            return '';
        } else {
            stream_set_blocking ( $fp, $block );
            stream_set_timeout ( $fp, $timeout );
            @fwrite ( $fp, $out );
            $status = stream_get_meta_data ( $fp );
            if (! $status ['timed_out']) {
                while ( ! feof ( $fp ) ) {
                    if (($header = @fgets ( $fp )) && ($header == "\r\n" || $header == "\n")) {
                        break;
                    }
                }

                $stop = false;
                while ( ! feof ( $fp ) && ! $stop ) {
                    $data = fread ( $fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit) );
                    $return .= $data;
                    if ($limit) {
                        $limit -= strlen ( $data );
                        $stop = $limit <= 0;
                    }
                }
            }
            @fclose ( $fp );
            return $return;
        }
    }

    /**
     * 下载文件
     * 可以指定下载显示的文件名，并自动发送相应的Header信息
     * 如果指定了content参数，则下载该参数的内容
     *
     * @static
     *
     * @access public
     * @param string $filename
     *            下载文件名
     * @param string $showname
     *            下载显示的文件名
     * @param string $content
     *            下载的内容
     * @param integer $expire
     *            下载内容浏览器缓存时间
     * @return void
     */
    static public function download($filename, $showname = '', $content = '', $expire = 180) {
        if (is_file ( $filename )) {
            $length = filesize ( $filename );
        } elseif (is_file ( UPLOAD_PATH . $filename )) {
            $filename = UPLOAD_PATH . $filename;
            $length = filesize ( $filename );
        } elseif ($content != '') {
            $length = strlen ( $content );
        } else {
            E ( $filename . L ( '下载文件不存在！' ) );
        }
        if (empty ( $showname )) {
            $showname = $filename;
        }
        $showname = basename ( $showname );
        if (! empty ( $filename )) {
            $finfo = new \finfo ( FILEINFO_MIME );
            $type = $finfo->file ( $filename );
        } else {
            $type = "application/octet-stream";
        }
        // 发送Http Header信息 开始下载
        header ( "Pragma: public" );
        header ( "Cache-control: max-age=" . $expire );
        // header('Cache-Control: no-store, no-cache, must-revalidate');
        header ( "Expires: " . gmdate ( "D, d M Y H:i:s", time () + $expire ) . "GMT" );
        header ( "Last-Modified: " . gmdate ( "D, d M Y H:i:s", time () ) . "GMT" );
        header ( "Content-Disposition: attachment; filename=" . $showname );
        header ( "Content-Length: " . $length );
        header ( "Content-type: " . $type );
        header ( 'Content-Encoding: none' );
        header ( "Content-Transfer-Encoding: binary" );
        if ($content == '') {
            readfile ( $filename );
        } else {
            echo ($content);
        }
        exit ();
    }

    /**
     * 显示HTTP Header 信息
     *
     * @return string
     */
    static function getHeaderInfo($header = '', $echo = true) {
        ob_start ();
        $headers = getallheaders ();
        if (! empty ( $header )) {
            $info = $headers [$header];
            echo ($header . ':' . $info . "\n");
            ;
        } else {
            foreach ( $headers as $key => $val ) {
                echo ("$key:$val\n");
            }
        }
        $output = ob_get_clean ();
        if ($echo) {
            echo (nl2br ( $output ));
        } else {
            return $output;
        }
    }

    /**
     * HTTP Protocol defined status codes
     *
     * @param int $num
     */
    static function sendHttpStatus($code) {
        static $_status = array (
            // Informational 1xx
            100 => 'Continue',
            101 => 'Switching Protocols',

            // Success 2xx
            200 => 'OK',
            201 => 'Created',
            202 => 'Accepted',
            203 => 'Non-Authoritative Information',
            204 => 'No Content',
            205 => 'Reset Content',
            206 => 'Partial Content',

            // Redirection 3xx
            300 => 'Multiple Choices',
            301 => 'Moved Permanently',
            302 => 'Found', // 1.1
            303 => 'See Other',
            304 => 'Not Modified',
            305 => 'Use Proxy',
            // 306 is deprecated but reserved
            307 => 'Temporary Redirect',

            // Client Error 4xx
            400 => 'Bad Request',
            401 => 'Unauthorized',
            402 => 'Payment Required',
            403 => 'Forbidden',
            404 => 'Not Found',
            405 => 'Method Not Allowed',
            406 => 'Not Acceptable',
            407 => 'Proxy Authentication Required',
            408 => 'Request Timeout',
            409 => 'Conflict',
            410 => 'Gone',
            411 => 'Length Required',
            412 => 'Precondition Failed',
            413 => 'Request Entity Too Large',
            414 => 'Request-URI Too Long',
            415 => 'Unsupported Media Type',
            416 => 'Requested Range Not Satisfiable',
            417 => 'Expectation Failed',

            // Server Error 5xx
            500 => 'Internal Server Error',
            501 => 'Not Implemented',
            502 => 'Bad Gateway',
            503 => 'Service Unavailable',
            504 => 'Gateway Timeout',
            505 => 'HTTP Version Not Supported',
            509 => 'Bandwidth Limit Exceeded'
        );
        if (isset ( $_status [$code] )) {
            header ( 'HTTP/1.1 ' . $code . ' ' . $_status [$code] );
        }
    }
}//类定义结束